
/*
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */


#include "config.h"

#include <stdio.h>

#include "main.h"
#include "misc.h"
#include "color.h"
#include "pos.h"
#include "libmooigraph.h"
#include "lmg.h"

/* drawing mode 0 is centered, 1 is wide drawing
 * int viewmode; toggled with the gtk+ gui
 */

int maxx = 0;
int maxy = 0;
struct dn **levels = NULL;
struct de *del = NULL;
static int dummyw = 15;
static int xspacing = 15;
static int yspacing = 50;
static int *hlevels = NULL;
static int *wlevels = NULL;
static void setx0 (void);
static void sety0 (void);
static void center (void);
static void wide (void);
static void setx1 (void);

void
pos_clear (void)
{
  int i;
  struct dn *ptr;
  struct dn *ptr2;

  if (levels)
    {
      for (i = 0; i < nlevels; i++)
	{
	  ptr = levels[i];
	  while (ptr)
	    {
	      ptr2 = ptr->next;
	      mgr_free (ptr);
	      ptr = ptr2;
	    }
	}
      levels = NULL;
      nlevels = 0;
    }

  if (hlevels)
    {
      mgr_free (hlevels);
      hlevels = NULL;
    }

  if (wlevels)
    {
      mgr_free (wlevels);
      wlevels = NULL;
    }
  return;
}

void
position (void)
{
  struct dn *ptr;
  int i;
  maxx = 0;
  maxy = 0;
  hlevels = mgr_malloc (nlevels * sizeof (int));
  wlevels = mgr_malloc (nlevels * sizeof (int));
  setx0 ();
  sety0 ();
  if (viewmode == 1)
    {
      wide ();
    }
  else
    {
      center ();
    }
  setx1 ();

  /* drawing y size */
  maxy = 0;
  for (i = 0; i < nlevels; i++)
    {
      ptr = levels[i];
      while (ptr)
	{
	  if (ptr->y2 > maxy)
	    {
	      maxy = ptr->y2;
	    }
	  ptr = ptr->next;
	}
    }

  /* for zooming */
  if (maxx == 0)
    {
      maxx = 1;
    }
  if (maxy == 0)
    {
      maxy = 1;
    }

  return;
}

static void
setx0 (void)
{
  int i = 0;
  int x0 = 0;
  int w = 0;
  struct dn *ptr = NULL;
  maxx = 0;
  for (i = 0; i < nlevels; i++)
    {
      x0 = 0;
      ptr = levels[i];
      while (ptr)
	{
	  ptr->x0 = x0;
	  if (ptr->un)
	    {
	      w = ptr->un->nx;
	    }
	  else
	    {
	      w = dummyw;
	    }
	  x0 = x0 + w + xspacing;
	  ptr = ptr->next;
	}
      if (x0 > maxx)
	{
	  maxx = x0;
	}
      wlevels[i] = x0;
    }

  return;
}

static void
sety0 (void)
{
  int i;
  struct dn *ptr;
  int maxh;
  int y0;
  y0 = 0;
  for (i = 0; i < nlevels; i++)
    {
      ptr = levels[i];
      maxh = 0;
      while (ptr)
	{
	  ptr->y0 = y0;
	  if (ptr->un)
	    {
	      if (ptr->un->ny > maxh)
		{
		  maxh = ptr->un->ny;
		}
	    }
	  ptr = ptr->next;
	}
      hlevels[i] = maxh;
      y0 = y0 + maxh + yspacing;
      if (y0 > maxy)
	{
	  maxy = y0;
	}
    }

  return;
}

struct dn *
getdn (int level, int pos)
{
  struct dn *ptr;
  ptr = levels[level];
  while (ptr)
    {
      if (ptr->pos == pos)
	{
	  return (ptr);
	}
      ptr = ptr->next;
    }
  return (NULL);
}

static void
center (void)
{
  int i;
  struct dn *ptr;
  int delta;
  for (i = 0; i < nlevels; i++)
    {
      delta = maxx - wlevels[i];
      delta = delta / 2;
      if (delta)
	{
	  ptr = levels[i];
	  while (ptr)
	    {
	      ptr->x0 = ptr->x0 + delta;
	      ptr = ptr->next;
	    }
	}
    }
  return;
}


static void
wide (void)
{
  int i;
  struct dn *ptr;
  int delta;
  int w = 0;
  int x0 = 0;
  for (i = 0; i < nlevels; i++)
    {
      x0 = 0;
      delta = maxx - wlevels[i];
      if (lmg_nnal (i))
	{
	  delta = delta / lmg_nnal (i);
	}
      else
	{
	  delta = delta / 2;
	}
      if (delta)
	{
	  ptr = levels[i];
	  while (ptr)
	    {
	      ptr->x0 = x0;
	      if (ptr->un)
		{
		  w = ptr->un->nx;
		}
	      else
		{
		  w = dummyw;
		}
	      x0 = x0 + w + delta;
	      ptr = ptr->next;
	    }
	}
    }
  return;
}

static void
setx1 (void)
{
  int i;
  struct dn *ptr;
  for (i = 0; i < nlevels; i++)
    {
      ptr = levels[i];
      while (ptr)
	{
	  if (ptr->un)
	    {
	      ptr->x1 = ptr->x0 + (ptr->un->nx / 2);
	      ptr->y1 = ptr->y0;
	      ptr->x2 = ptr->x0 + (ptr->un->nx / 2);
	      ptr->y2 = ptr->y0 + ptr->un->ny;
	      ptr->y3 = ptr->y0 + hlevels[i];
	    }
	  else
	    {
	      /* dummy node */
	      ptr->x1 = ptr->x0;
	      ptr->y1 = ptr->y0;
	      ptr->x2 = ptr->x0;
	      ptr->y2 = ptr->y0 + hlevels[i];
	      ptr->y3 = ptr->y0 + hlevels[i];
	    }
	  ptr = ptr->next;
	}
    }
  return;
}

/* End */
